﻿using System;
using System.Collections.Generic;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System.IO;
using System.Text;
using TextCopy;

/// <summary>
/// 代码生成端
/// </summary>
public enum EGenSide
{
    /// <summary>
    /// 客户端
    /// </summary>
    Client = 1,

    /// <summary>
    /// 服务器
    /// </summary>
    Server = 2,
}

/// <summary>
/// 代码生成器
/// </summary>
public class CodeGenerator
{
    /// <summary>
    /// 字段范围 s:服务器 c:客户端
    /// </summary>
    private const int RowSideOffset = 0;
    /// <summary>
    /// 字段类型
    /// </summary>
    private const int RowTypeOffset = 1;
    /// <summary>
    /// 字段名称
    /// </summary>
    private const int RowFieldOffset = 2;
    /// <summary>
    /// 字段注释信息
    /// </summary>
    private const int RowCommentOffset = 3;

    /// <summary>
    /// 生成代码到剪贴板
    /// </summary>
    /// <param name="filePath">文件路径</param>
    /// <param name="templateFilePath">模板文件路径</param>
    /// <param name="genSide">代码生成端</param>
    public void GeneratorCode2ClipBoard(string filePath, string templateFilePath, EGenSide genSide)
    {
        if (string.IsNullOrEmpty(filePath))
        {
            Debug.LogError("配置表文件路径为空！");
            return;
        }

        if (!File.Exists(filePath))
        {
            Debug.LogError($"配置表文件路径不存在！ {filePath}");
            return;
        }

        if (string.IsNullOrEmpty(templateFilePath))
        {
            Debug.LogError("模板文件路径为空！");
            return;
        }

        if (!File.Exists(templateFilePath))
        {
            Debug.LogError($"模板文件路径不存在！ {templateFilePath}");
            return;
        }

        try
        {
            FileStream fs = File.OpenRead(filePath);
            try
            {
                XSSFWorkbook wk = new XSSFWorkbook(fs);
                int sheetCnt = wk.NumberOfSheets;
                StringBuilder sb = new StringBuilder();
                sb.AppendLine("选择需要生成的Sheet(直接回车默认选择第1个)");
                int defualtSelectIndex = -1;
                for (int i = 0; i < sheetCnt; i++)
                {
                    ISheet sheet = wk.GetSheetAt(i);
                    string[] sheetNames = sheet.SheetName.Split('|');
                    if (sheetNames.Length != 2 || string.IsNullOrEmpty(sheetNames[0]) || string.IsNullOrEmpty(sheetNames[1]))
                    {
                        continue;
                    }
                    if (defualtSelectIndex < 0)  //默认选中第1个sheet
                    {
                        defualtSelectIndex = i;
                    }
                    sb.AppendFormat("{0}.{1}\n", i, sheet.SheetName);
                }
                Debug.LogDarkGreen(sb.ToString());

                //需要处理的Sheet
                string inputStr = Console.ReadLine();
                int.TryParse(inputStr, out int inputNum);
                if (inputNum > 0)
                {
                    defualtSelectIndex = inputNum;
                }
                ISheet targetSheet = wk.GetSheetAt(defualtSelectIndex);
                StreamReader streamReader = new StreamReader(templateFilePath);
                Debug.LogYellow($"正在加载Sheet:{targetSheet.SheetName}");
                _GeneratorCode2ClipBoard(targetSheet, genSide, streamReader.ReadToEnd());  //调用具体实现函数
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
        }
        catch (Exception)
        {
            Debug.LogError(string.Format("加载文件：{0}  失败，请检查路径是否有误!!!", filePath));
        }
    }

    /// <summary>
    /// 生成代码到剪贴板具体实现
    /// </summary>
    /// <param name="sheet">sheet页具体信息</param>
    /// <param name="genSide">代码生产端</param>
    /// <param name="templateStr">模板文本 _FieldCode:表示字段声明</param>
    private void _GeneratorCode2ClipBoard(ISheet sheet, EGenSide genSide, string templateStr)
    {
        IRow rowSide = sheet.GetRow(sheet.FirstRowNum + RowSideOffset);  //字段范围 s:服务器 c:客户端
        IRow rowFieldType = sheet.GetRow(sheet.FirstRowNum + RowTypeOffset);  //字段类型
        IRow rowField = sheet.GetRow(sheet.FirstRowNum + RowFieldOffset);  //字段名称
        IRow rowComment = sheet.GetRow(sheet.FirstRowNum + RowCommentOffset);  //字段注释信息
        int columnNum = rowSide.LastCellNum;  //最后一列

        StringBuilder fieldSb = new StringBuilder();  //字段声明文本
        StringBuilder parseSb = new StringBuilder();  //字段解析文本

        for (int col = 0; col < columnNum; col++)
        {
            if (rowSide.GetCell(col) == null || string.IsNullOrEmpty(rowSide.GetCell(col).ToString()))
                continue;

            string side = rowSide.GetCell(col).StringCellValue;
            if (genSide == EGenSide.Client && !side.Contains("c"))
                continue;
            if (genSide == EGenSide.Server && !side.Contains("s"))
                continue;

            string fieldType = rowFieldType.GetCell(col).StringCellValue;
            string field = rowField.GetCell(col).StringCellValue;
            if (field == "ID")  //ID不处理
                continue;

            string commment = rowComment.GetCell(col).StringCellValue;

            fieldSb.AppendLine(GenFieldStr(fieldType, field, commment));
        }

        string sheetChineseName = sheet.SheetName.Split('|')[0];
        string sheetClassName = sheet.SheetName.Split('|')[1];

        string className = $"{sheetClassName[0].ToString().ToUpper() + sheetClassName.Substring(1)}Cfg";  //类名首字母大写
        string classComment = $"{sheetChineseName} {sheetClassName}.xml"; 

        string resultStr = templateStr.Replace("_CLASSCOMMENT", classComment);  //类注释
        resultStr = resultStr.Replace("_CLASSNAME", className);  //类名
        resultStr = resultStr.Replace("_FIELDCODE", fieldSb.ToString());  //字段声明

        Clipboard.SetText(resultStr);
        Debug.LogGreen("生成的代码已复制到剪贴板");
    }

    /// <summary>
    /// 生成字段代码
    /// </summary>
    /// <param name="fieldType">字段类型</param>
    /// <param name="field">字段名</param>
    /// <param name="comment">注释</param>
    /// <returns>返回代码文本</returns>
    private string GenFieldStr(string fieldType, string field, string comment)
    {
        string template = "/// <summary>\n/// _COMMENT\n/// </summary>\n[ConfigMark]\npublic readonly _FIELDTYPE _FIELD;";

        string resultStr = template.Replace("_COMMENT", comment); //注释
        resultStr = resultStr.Replace("_FIELDTYPE", fieldType);  //字段类型
        resultStr = resultStr.Replace("_FIELD", field[0].ToString().ToUpper() + field.Substring(1));  //字段 首字母大写

        return resultStr;
    }
   
}
